#include "config.h"
#include "ringbuffer.h"

#define LOG_UART_DEINIT     UART0_DeInit
#define LOG_UART_NUM        (UART0)
#define LOG_UART_IO_NUM     (IO_UART0)
#define LOG_MIX_NUM         (1)
#define LOG_BAUDRATE        (115200)
#define LOG_UART_DIV_CLK    ((SYSTEM_CLOCK_24MHZ)/(LOG_BAUDRATE))

#define LOG_GPIO_GRP        (GPIOA0)
#define LOG_GPIO_TX_PIN     (12)
#define LOG_GPIO_RX_PIN     (5)

void UART0_irq_handle(UINT8 byte)
{
    RingBuffer_Write_Byte(byte);
    // UARTTxByte(LOG_UART_NUM, (uint8_t)byte);
}

/**
 * @brief 调试串口初始化
 * @param 无
 * @return 无
 */
void log_port_init(void)
{
    RingBuffer_Init();
    LOG_UART_DEINIT();  //clear all UART Register
    UART_IO_Init(LOG_UART_IO_NUM, LOG_MIX_NUM); //PA0.5->RXD0, PA0.12->TXD0
    //baudrate=sysclock 24M/208=115200
    UARTInit(LOG_UART_NUM, (LOG_UART_DIV_CLK), UART_PAR_NONE);
    UARTInitRxTxIntEn(LOG_UART_NUM, LOG_UART_DIV_CLK, UART_PAR_NONE);   //baudrate=sysclock 24M/208=115200 tx rx int enabled 
    UART0_Int_Enable();
}

/**
 * @brief 日志串口释放
 * @param 无
 * @return 无
 */
void log_deinit(void)
{
    //PA0.5->RXD0, PA0.12->TXD0
    GPIO_Init(LOG_GPIO_GRP, LOG_GPIO_TX_PIN, Output);
    GPIO_Init(LOG_GPIO_GRP, LOG_GPIO_RX_PIN, Output);

    GPIO_Write_Low(LOG_GPIO_GRP, LOG_GPIO_TX_PIN);
    GPIO_Write_Low(LOG_GPIO_GRP, LOG_GPIO_RX_PIN);
}

static inline void __putchar__ (char ch) 
{
    UARTTxByte(LOG_UART_NUM,ch);
}

int log_send_char(uint8_t ch)
{
    UARTTxByte(LOG_UART_NUM, (uint8_t)ch);
    return 1;
}

int log_recv_char(void)
{
    int ret = 0;
    uint8_t byte = 0;
    ret = RingBuffer_Read_Byte(&byte);
    if(ret) {
        return byte;
    }
    return -1;
}

static char *myitoa(int value, int* string, int radix)
{
    int tmp[33];
    int* tp = tmp;
    int i;
    unsigned v;
    int sign;
    int* sp;

    if (radix > 36 || radix <= 1)
    {
        return 0;
    }

    sign = (radix == 10 && value < 0);
    if (sign) {
        v = -value;
    } else {
        v = (unsigned)value;
    }
    while (v || tp == tmp)
    {
        i = v % radix;
        v = v / radix;
        if (i < 10) {
            *tp++ = i+'0';
        } else {
            *tp++ = i + 'a' - 10;
        }
    }

    sp = string;
    if (sign) {
        *sp++ = '-';
    }
    while (tp > tmp) {
        *sp++ = *--tp;
    }
    *sp = 0;
    return string;
}

/**
 * @brief 日志格式化输出
 * @param 无
 * @return 无
 */
void log_print(const char *fmt, ...)
{
    const int *s;
    int d;
    char ch, *pbuf;
    int buf[16];
    va_list ap;
    va_start(ap, fmt);
    while (*fmt)
    {
        if (*fmt != '%') {
              __putchar__(*fmt++);
            continue;
        }
        switch (*++fmt) {
            case 's':
                s = va_arg(ap, const char *);
                for ( ; *s; s++) {
                    __putchar__(*s);
                }
                break;
            case 'd':
                d = va_arg(ap, int);
                myitoa(d, buf, 10);
                for (s = buf; *s; s++) {
                    __putchar__(*s);
                }
                break;
            case 'x':
            case 'X':
                d = va_arg(ap, int);
                myitoa(d, buf, 16);
                for (s = buf; *s; s++) {
                    __putchar__(*s);
                }
                break;
            case 'c':
            case 'C':
                ch = (unsigned char)va_arg(ap, int);
                pbuf = &ch;
                __putchar__(*pbuf);
                break;
            default:
                __putchar__(*fmt);
                break;
        }
        fmt++;
    }
    va_end(ap);
}




